#include "tableform.h"
#include "ui_tableform.h"
#include "headerview.h"
#include "itemdialog.h"
#include "operatordialog.h"
#include "storedialog.h"
#include "organizationdialog.h"

#include <QtSql>
#include <QMenuBar>
#include <QInputDialog>
#include <QMessageBox>
#include <QCompleter>

TableForm::TableForm(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::TableForm)
{
    ui->setupUi(this);

    model = 0;

    headerView = new HeaderView(Qt::Horizontal);

    ui->tableView->setHorizontalHeader(headerView);
    ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    //ui->tableView->setSelectionMode(QAbstractItemView::ContiguousSelection);
    ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);

    addAction = new QAction(QIcon(":/icons/icons/Add.png"), tr("Add"), this);
    deleteAction = new QAction(QIcon(":/icons/icons/Delete.png"), tr("Delete"), this);
    editAction = new QAction(QIcon(":/icons/icons/Pen.png"), tr("Edit"), this);

    addAction->setShortcut(QKeySequence(tr("+")));
    deleteAction->setShortcut(QKeySequence(tr("-")));
    editAction->setShortcut(QKeySequence(tr("Enter")));

    connect(addAction, SIGNAL(triggered()), this, SLOT(add()));
    connect(editAction, SIGNAL(triggered()), this, SLOT(edit()));
    connect(deleteAction, SIGNAL(triggered()), this, SLOT(remove()));

    ui->tableView->addAction(addAction);
    ui->tableView->addAction(deleteAction);
    ui->tableView->addAction(editAction);

    QMenuBar *menuBar = new QMenuBar(0);
    menuBar->addAction(addAction);
    menuBar->addAction(deleteAction);
    menuBar->addAction(editAction);

    ui->table_groupBox->layout()->setMenuBar(menuBar);

    this->updateActions();
}

TableForm::~TableForm()
{
    delete ui;
}

void TableForm::setTable(const QString &table)
{
    if(model) delete(model);
    model = new QSqlRelationalTableModel(this);

    model->setEditStrategy(QSqlTableModel::OnManualSubmit);
    model->setTable(table);

    if(table == "items"){
        this->setWindowTitle(tr("Items"));
        ui->table_groupBox->setTitle(tr("Items"));
        this->setWindowIcon(QIcon(":/icons/icons/Barcode.png"));

       /* model->setRelation(model->fieldIndex("location_id"), QSqlRelation("locations", "id", "location"));
        model->setRelation(model->fieldIndex("type_id"), QSqlRelation("item_types", "id", "type"));
        model->setRelation(model->fieldIndex("operator_id"), QSqlRelation("operators", "id", "name"));
        model->setRelation(model->fieldIndex("status_id"), QSqlRelation("item_status", "id", "status"));
        */
    }
    else if(table == "operators"){
        this->setWindowTitle(tr("Operators"));
        ui->table_groupBox->setTitle(tr("Operators"));
        this->setWindowIcon(QIcon(":/icons/icons/Office Girl.png"));

        model->setRelation(model->fieldIndex("department_id"), QSqlRelation("departments", "id", "department"));
    }
    else if(table == "departments"){
        this->setWindowTitle(tr("Departments"));
        ui->table_groupBox->setTitle(tr("Departments"));
        this->setWindowIcon(QIcon(":/icons/icons/Clients.png"));

        model->setHeaderData(model->fieldIndex("department"), Qt::Horizontal, tr("Department"), Qt::EditRole);

    }
    else if(table == "stores"){
        this->setWindowTitle(tr("Stores"));
        ui->table_groupBox->setTitle(tr("Stores"));
        this->setWindowIcon(QIcon(":/icons/icons/Folder.png"));

        model->setRelation(model->fieldIndex("operator_id"), QSqlRelation("operators", "id", "name"));

    }
    else if(table == "organizations"){
        this->setWindowTitle(tr("Organizations"));
        ui->table_groupBox->setTitle(tr("Organizations"));
        this->setWindowIcon(QIcon(":/icons/icons/Home.png"));
    }

    else this->setWindowTitle(model->tableName());
    model->select();

    //connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(dataChanged(QModelIndex, QModelIndex)));

    ui->tableView->disconnect();
    ui->tableView->setModel(model);
    //if(!qApp->property("show_id").toBool()) ui->tableView->hideColumn(model->fieldIndex("id"));

    if(model->tableName() == "items"){
        model->setHeaderData(model->fieldIndex("measure"), Qt::Horizontal, tr("Measure"), Qt::EditRole);
        model->setHeaderData(model->fieldIndex("price"), Qt::Horizontal, tr("Price"), Qt::EditRole);
        model->setHeaderData(model->fieldIndex("name"), Qt::Horizontal, tr("Name"), Qt::EditRole);
    }
    else if(model->tableName() == "operators"){
        model->setHeaderData(model->fieldIndex("name"), Qt::Horizontal, tr("Name"), Qt::EditRole);
        model->setHeaderData(model->fieldIndex("note"), Qt::Horizontal, tr("Note"), Qt::EditRole);
        model->setHeaderData(model->fieldIndex("department"), Qt::Horizontal, tr("Department"), Qt::EditRole);
    }
    else if(model->tableName() == "stores"){
        model->setHeaderData(model->fieldIndex("store"), Qt::Horizontal, tr("Store"), Qt::EditRole);
        model->setHeaderData(model->fieldIndex("name"), Qt::Horizontal, tr("Name"), Qt::EditRole);
        model->setHeaderData(model->fieldIndex("note"), Qt::Horizontal, tr("Note"), Qt::EditRole);
    }
    else if(model->tableName() == "organizations"){
        model->setHeaderData(model->fieldIndex("organization"), Qt::Horizontal, tr("Organization"), Qt::EditRole);
        model->setHeaderData(model->fieldIndex("town"), Qt::Horizontal, tr("Town"), Qt::EditRole);
        model->setHeaderData(model->fieldIndex("street"), Qt::Horizontal, tr("Street"), Qt::EditRole);
        model->setHeaderData(model->fieldIndex("no"), Qt::Horizontal, tr("No"), Qt::EditRole);
    }
    ui->tableView->hideColumn(model->fieldIndex("id"));

    connect(ui->tableView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(itemSelected(QModelIndex,QModelIndex)));
    connect(ui->tableView, SIGNAL(activated(QModelIndex)), this, SLOT(activated(QModelIndex)));

    this->updateActions();
    this->loadCompleter();
}


void TableForm::itemSelected(const QModelIndex &current, const QModelIndex& previous)
{
    Q_UNUSED(current);
    Q_UNUSED(previous);
    //qDebug() << "Item selected";
    this->updateActions();
}

void TableForm::updateActions()
{
    bool enableAdd = qobject_cast<QSqlRelationalTableModel *>(ui->tableView->model());
    bool enableEditDel = enableAdd && ui->tableView->currentIndex().isValid();

    addAction->setEnabled(enableAdd);
    editAction->setEnabled(enableEditDel);
    deleteAction->setEnabled(enableEditDel);
}

void TableForm::add()
{
    if(model->tableName() == "items"){
        this->addItem();
    }
    else if(model->tableName() == "operators"){
        this->addOperator();
    }
    else if(model->tableName() == "departments"){
        this->addDepartment();
    }
    else if(model->tableName() == "stores"){
        this->addStore();
    }
    else if(model->tableName() == "organizations"){
        this->addOrganization();
    }
}

void TableForm::edit()
{
    QModelIndex index = ui->tableView->selectionModel()->currentIndex();
    if(index.isValid()){
        if(model->tableName() == "items"){
            this->editItem(index);
        }
        else if(model->tableName() == "operators"){
            this->editOperator(index);
        }
        else if(model->tableName() == "departments"){
            this->editDepartment(index);
        }
        else if(model->tableName() == "stores"){
            this->editStore(index);
        }
        else if(model->tableName() == "organizations"){
            this->editOrganization(index);
        }
    }
}

void TableForm::addItem()
{
    ItemDialog* dlg = new ItemDialog(this);
    if(dlg->exec() == QDialog::Accepted){
        QSqlQuery* query = new QSqlQuery(QSqlDatabase::database());
        if(!query->exec(QString("INSERT INTO `items` (`name`,`measure`,`price`) VALUES('%1', '%2', '%3')")
                        .arg(dlg->getName())
                        .arg(dlg->getMeasure())
                        .arg(dlg->getPrice())
                        )){
            qDebug() << "Can not save data into database. Sql error: " << query->lastError().text();
            QMessageBox msgBox;
            msgBox.setText(query->lastError().text());
            msgBox.exec();
        }
    }
    delete(dlg);
    model->submitAll();
}

void TableForm::editItem(const QModelIndex &index)
{
    QSqlRecord record = model->record(index.row());
    ItemDialog* dlg = new ItemDialog(this);
    dlg->setItem(record.field("id").value().toInt());
    if(dlg->exec() == QDialog::Accepted){
        QSqlQuery* query = new QSqlQuery(QSqlDatabase::database());
        if(!query->exec(QString("UPDATE `items` SET `name`='%1',`measure`='%2',`price`='%3' WHERE `id`='%4'")
                        .arg(dlg->getName())
                        .arg(dlg->getMeasure())
                        .arg(dlg->getPrice())
                        .arg(record.field("id").value().toInt())
                        )){
            qDebug() << "Can not save edited data into database. Sql error: " << query->lastError().text();
            QMessageBox msgBox;
            msgBox.setText(query->lastError().text());
            msgBox.exec();
        }
    }
    delete(dlg);
    model->submitAll();
}

void TableForm::activated(const QModelIndex &index)
{
    if(index.isValid()){
        if(model->tableName() == "items"){
            this->editItem(index);
        }
        else if(model->tableName() == "operators"){
            this->editOperator(index);
        }
        else if(model->tableName() == "departments"){
            this->editDepartment(index);
        }
        else if(model->tableName() == "stores"){
            this->editStore(index);
        }
        else if(model->tableName() == "organizations"){
            this->editOrganization(index);
        }
    }
}

void TableForm::editDepartment(const QModelIndex& index)
{
    QSqlRecord record = model->record(index.row());
    bool ok;
    QString text = QInputDialog::getText(this, tr("Edit department"),
                                              tr("Department:"), QLineEdit::Normal,
                                              record.field("department").value().toString(), &ok);
    if (ok && !text.isEmpty()){
        QSqlQuery* query = new QSqlQuery();
        if(!query->exec(QString("UPDATE departments SET `department`='%1' WHERE `id`='%2'")
                        .arg(text)
                        .arg(record.field("id").value().toInt())
                        )){
            qDebug() << "Sql error: " << query->lastError().text();
            QMessageBox msgBox;
            msgBox.setText(query->lastError().text());
            msgBox.exec();
        }
        else{
            model->submitAll();
        }
    }
}

void TableForm::addDepartment()
{
    bool ok;
    QString text = QInputDialog::getText(this, tr("Add department"),
                                              tr("Department:"), QLineEdit::Normal,
                                              "", &ok);
    if (ok && !text.isEmpty()){
        QSqlQuery* query = new QSqlQuery();
        if(!query->exec(QString("INSERT INTO departments (`department`) VALUES ('%1')").arg(text))){
            qDebug() << "Sql error: " << query->lastError().text();
            QMessageBox msgBox;
            msgBox.setText(query->lastError().text());
            msgBox.exec();
        }
        else{
            model->submitAll();
        }
    }
}

void TableForm::addOperator()
{
    OperatorDialog* dlg = new OperatorDialog(this);
    if(dlg->exec() == QDialog::Accepted){
        QSqlQuery* query = new QSqlQuery(QSqlDatabase::database());
        if(!query->exec(QString("INSERT INTO `operators` (`name`,`note`,`department_id`) VALUES('%1', '%2', '%3')")
                        .arg(dlg->getName())
                        .arg(dlg->getNote())
                        .arg(dlg->getDepartmentId())
                        )){
            qDebug() << "Can not save data into database. Sql error: " << query->lastError().text();
            QMessageBox msgBox;
            msgBox.setText(query->lastError().text());
            msgBox.exec();
        }
    }
    delete(dlg);
    model->submitAll();
}

void TableForm::editOperator(const QModelIndex &index)
{
    QSqlRecord record = model->record(index.row());
    OperatorDialog* dlg = new OperatorDialog(this);
    dlg->setOperator(record.field("id").value().toInt());
    if(dlg->exec() == QDialog::Accepted){
        QSqlQuery* query = new QSqlQuery(QSqlDatabase::database());
        if(!query->exec(QString("UPDATE `operators` SET `name`='%1',`note`='%2',`department_id`='%3' WHERE `id`='%4'")
                        .arg(dlg->getName())
                        .arg(dlg->getNote())
                        .arg(dlg->getDepartmentId())
                        .arg(record.field("id").value().toInt())
                        )){
            qDebug() << "Can not save edited data into database. Sql error: " << query->lastError().text();
            QMessageBox msgBox;
            msgBox.setText(query->lastError().text());
            msgBox.exec();
        }
    }
    delete(dlg);
    model->submitAll();
}

void TableForm::remove()
{
    QModelIndexList list(ui->tableView->selectionModel()->selectedRows(model->fieldIndex("id")));
    if(list.isEmpty()) return;
    int ret = QMessageBox::question(this, tr("Nomenklatures"),
                                tr("Do you want to delete this %1 records?\nThis could not be restored!")
                                .arg(list.count()),
                                QMessageBox::Ok | QMessageBox::Cancel);
    if(ret == QMessageBox::Cancel) return;
    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));

    QString ids;
    for (int i = 0; i < list.size(); ++i) {
        if(list.at(i).data(Qt::EditRole).toString() != "1"){
            ids.append(list.at(i).data(Qt::EditRole).toString());
            if(list.at(i) != list.last()) ids.append(',');
        }
    }
    QSqlQuery* query = new QSqlQuery(QSqlDatabase::database());
    if(!query->exec(QString("DELETE from `%1` WHERE `id` IN (%2)")
                    .arg(model->tableName())
                    .arg(ids))){
            qDebug() << "Sql error: " << query->lastError().text();
            QMessageBox msgBox;
            msgBox.setText(query->lastError().text());
            msgBox.exec();
    }
    QApplication::restoreOverrideCursor();
    model->submitAll();
}

void TableForm::addStore()
{
    StoreDialog* dlg = new StoreDialog(this);
    if(dlg->exec() == QDialog::Accepted){
        QSqlQuery* query = new QSqlQuery(QSqlDatabase::database());
        if(!query->exec(QString("INSERT INTO `stores` (`store`,`operator_id`,`note`) VALUES('%1', '%2', '%3')")
                        .arg(dlg->getStore())
                        .arg(dlg->getOperatorId())
                        .arg(dlg->getNote())
                        )){
            qDebug() << "Can not save data into database. Sql query: " << query->lastQuery();
            QMessageBox msgBox;
            msgBox.setText(query->lastError().text());
            msgBox.exec();
        }
    }
    delete(dlg);
    model->submitAll();
}

void TableForm::editStore(const QModelIndex &index)
{
    QSqlRecord record = model->record(index.row());
    StoreDialog* dlg = new StoreDialog(this);
    dlg->setStore(record.field("id").value().toInt());
    if(dlg->exec() == QDialog::Accepted){
        QSqlQuery* query = new QSqlQuery(QSqlDatabase::database());
        if(!query->exec(QString("UPDATE `stores` SET `store`='%1',`note`='%2',`operator_id`='%3' WHERE `id`='%4'")
                        .arg(dlg->getStore())
                        .arg(dlg->getNote())
                        .arg(dlg->getOperatorId())
                        .arg(record.field("id").value().toInt())
                        )){
            qDebug() << "Can not save edited data into database. Sql error: " << query->lastError().text();
            QMessageBox msgBox;
            msgBox.setText(query->lastError().text());
            msgBox.exec();
        }
    }
    delete(dlg);
    model->submitAll();
}

void TableForm::addOrganization()
{
    OrganizationDialog* dlg = new OrganizationDialog(this);
    if(dlg->exec() == QDialog::Accepted){
        QSqlQuery* query = new QSqlQuery(QSqlDatabase::database());
        if(!query->exec(QString("INSERT INTO `organizations` (`organization`,`town`,`street`,`no`) VALUES('%1', '%2', '%3', '%4')")
                        .arg(dlg->getOrganization())
                        .arg(dlg->getTown())
                        .arg(dlg->getStreet())
                        .arg(dlg->getNo())
                        )){
            qDebug() << "Can not save data into database. Sql error: " << query->lastError().text();
            QMessageBox msgBox;
            msgBox.setText(query->lastError().text());
            msgBox.exec();
        }
    }
    delete(dlg);
    model->submitAll();
}

void TableForm::editOrganization(const QModelIndex &index)
{
    QSqlRecord record = model->record(index.row());
    OrganizationDialog* dlg = new OrganizationDialog(this);
    dlg->setOrganization(record.field("id").value().toInt());
    if(dlg->exec() == QDialog::Accepted){
        QSqlQuery* query = new QSqlQuery(QSqlDatabase::database());
        if(!query->exec(QString("UPDATE `organizations` SET `organization`='%1',`town`='%2',`street`='%3', `no`='%4' WHERE `id`='%5'")
                        .arg(dlg->getOrganization())
                        .arg(dlg->getTown())
                        .arg(dlg->getStreet())
                        .arg(dlg->getNo())
                        .arg(record.field("id").value().toInt())
                        )){
            qDebug() << "Can not save edited data into database. Sql error: " << query->lastError().text();
            QMessageBox msgBox;
            msgBox.setText(query->lastError().text());
            msgBox.exec();
        }
    }
    delete(dlg);
    model->submitAll();
}

void TableForm::on_filter_lineEdit_textChanged(const QString &arg1)
{
    QString filter = arg1;
    filter.replace("'", "''");
    if(filter.isEmpty()){
        model->setFilter(filter);
        return;
    }
    if(model->tableName() == "departments"){
        model->setFilter(
                    QString("department LIKE '%%1%'").arg(filter)
                    );
    }
    else if(model->tableName() == "items")
    {
        model->setFilter(
                    QString("name LIKE '%%1%' OR measure LIKE '%%1%'").arg(filter)
                    );
    }
    else if(model->tableName() == "operators")
    {
        model->setFilter(
        QString("name LIKE '%%1%' OR note LIKE '%%1%' OR department LIKE '%%1%'").arg(filter)
                    );
    }
    else if(model->tableName() == "organizations")
    {
        model->setFilter(
        QString("organization LIKE '%%1%'").arg(filter)
                    );
    }
    else if(model->tableName() == "stores")
    {
        model->setFilter(QString("store LIKE '%%1%'").arg(filter));
    }
}

void TableForm::loadCompleter()
{
    QSqlQuery* query = new QSqlQuery();

    if(model->tableName() == "departments"){
        if(!query->exec("SELECT `department` FROM `departments`")){
            qDebug() << tr("Sql error: \n%1").arg(query->lastError().text());
            QMessageBox msgBox;
            msgBox.setText(query->lastError().text());
            msgBox.exec();
            return;
        }
    }
    else if(model->tableName() == "items")
    {
        if(!query->exec("SELECT `name` FROM `items`")){
            qDebug() << tr("Sql error: \n%1").arg(query->lastError().text());
            QMessageBox msgBox;
            msgBox.setText(query->lastError().text());
            msgBox.exec();
            return;
        }
    }
    else if(model->tableName() == "operators")
    {
        if(!query->exec("SELECT `name` FROM `operators`")){
            qDebug() << tr("Sql error: \n%1").arg(query->lastError().text());
            QMessageBox msgBox;
            msgBox.setText(query->lastError().text());
            msgBox.exec();
            return;
        }
    }
    else if(model->tableName() == "organizations")
    {
        if(!query->exec("SELECT `organization` FROM `organizations`")){
            qDebug() << tr("Sql error: \n%1").arg(query->lastError().text());
            QMessageBox msgBox;
            msgBox.setText(query->lastError().text());
            msgBox.exec();
            return;
        }
    }
    else if(model->tableName() == "stores")
    {
        if(!query->exec("SELECT `store` FROM `stores`")){
            qDebug() << tr("Sql error: \n%1").arg(query->lastError().text());
            QMessageBox msgBox;
            msgBox.setText(query->lastError().text());
            msgBox.exec();
            return;
        }
    }
    QStringList wordList;
    while(query->next()){
        wordList << query->value(0).toString();
    }
    wordList.removeDuplicates();
    QCompleter *completer = new QCompleter(wordList, this);
    completer->setCaseSensitivity(Qt::CaseInsensitive);
    ui->filter_lineEdit->setCompleter(completer);
}
